Introduction to Firebase & Flutter
Firebase is a Google-backed application development platform that provides backend services that can be integrated into Flutter applications. It can help developers add authentication, cloud databases, file storage, analytics, crash reporting, messaging, server-side functionality, and other backend capabilities without building every backend service from scratch.
Flutter integrates with Firebase through the FlutterFire plugins. Firebase's official Flutter setup uses the Firebase CLI, FlutterFire CLI, firebase_core, and a generated firebase_options.dart configuration file. :contentReference[oaicite:0]{index=0}
1. What is Firebase?
Firebase is a platform that provides a collection of backend and application-development services. These services can be used by mobile, web, and other applications.
For a Flutter developer, Firebase can provide backend functionality such as:
Firebase maintains Flutter plugins for individual Firebase products, allowing Flutter applications to communicate with Firebase services through Dart APIs. :contentReference[oaicite:1]{index=1}
2. What is FlutterFire?
FlutterFire is the collection of official Flutter plugins that provides access to Firebase services from Flutter applications.
For example:
| Firebase Service |
Flutter Plugin |
Purpose |
| Firebase Core |
firebase_core |
Initializes Firebase in the application |
| Authentication |
firebase_auth |
User registration, login, and authentication |
| Cloud Firestore |
cloud_firestore |
Cloud-hosted NoSQL database |
| Realtime Database |
firebase_database |
Realtime data synchronization |
| Cloud Storage |
firebase_storage |
File and media storage |
| Cloud Messaging |
firebase_messaging |
Push notifications |
| Analytics |
firebase_analytics |
Application usage analytics |
| Crashlytics |
firebase_crashlytics |
Crash reporting and monitoring |
| Remote Config |
firebase_remote_config |
Remote application configuration |
The official Firebase Flutter documentation provides plugins for many Firebase products, including Authentication, Cloud Firestore, Cloud Storage, Cloud Messaging, Crashlytics, Analytics, Remote Config, and others. :contentReference[oaicite:2]{index=2}
3. Why Use Firebase with Flutter?
Flutter provides the frontend UI and application logic, while Firebase can provide backend services.
Flutter Application
|
v
FlutterFire
|
v
Firebase
|
+---- Authentication
+---- Firestore
+---- Storage
+---- Messaging
+---- Analytics
+---- Crashlytics
This combination can be useful when building applications that need authentication, cloud data, file uploads, notifications, analytics, or other backend capabilities.
4. Advantages of Firebase with Flutter
- Quick backend integration.
- Official Flutter plugins are available for many Firebase services.
- Authentication can be added without implementing an authentication server from scratch.
- Cloud databases can be integrated into Flutter applications.
- Files and images can be stored using Cloud Storage.
- Push notifications can be implemented using Firebase Cloud Messaging.
- Application crashes can be monitored using Crashlytics.
- Application usage can be analyzed with Analytics.
- Firebase services can be used across supported Flutter platforms.
5. Firebase Architecture with Flutter
Flutter UI
|
v
Application Logic
|
v
FlutterFire
|
+----------+----------+
| | |
v v v
Firebase Firebase Firebase
Auth Database Storage
| | |
+----------+----------+
|
v
Firebase Backend
6. Requirements for Firebase and Flutter
Before integrating Firebase, you should have:
- An editor such as Android Studio or Visual Studio Code.
- A supported Android, iOS, web, or other supported Flutter target.
Firebase's current Flutter setup documentation requires the Flutter SDK and platform-specific development requirements. For Android, the documentation currently lists Android 6.0 or higher and API level 23 or higher as requirements. :contentReference[oaicite:3]{index=3}
7. Create a Flutter Project
Create a new Flutter project using the Flutter CLI:
flutter create firebase_flutter_app
Move into the project directory:
cd firebase_flutter_app
Run the project:
flutter run
8. Create a Firebase Project
A Firebase project is the container that holds your Firebase applications and services.
General steps:
- Open the Firebase Console.
- Sign in with your Google account.
- Create a new Firebase project.
- Enter a project name.
- Complete the project creation process.
- Register the platforms that your Flutter application will use.
Firebase's Flutter documentation supports either selecting an existing Firebase project or creating a new project during the FlutterFire configuration process. :contentReference[oaicite:4]{index=4}
9. Firebase CLI
The Firebase CLI provides command-line tools for interacting with Firebase projects.
After installing the Firebase CLI, sign in with:
firebase login
10. Install FlutterFire CLI
The FlutterFire CLI helps configure a Flutter application with Firebase.
dart pub global activate flutterfire_cli
The official Firebase setup instructions use the FlutterFire CLI to configure the platforms selected for a Flutter project. :contentReference[oaicite:5]{index=5}
11. Configure Firebase with Flutter
From the root directory of your Flutter project, run:
flutterfire configure
The configuration workflow allows you to select the Firebase project and platforms for the Flutter application. It also generates a firebase_options.dart file in the lib/ directory. :contentReference[oaicite:6]{index=6}
12. What Does flutterfire configure Do?
The flutterfire configure command helps connect your Flutter project to Firebase.
It can:
- Allow you to select an existing Firebase project or create a new one.
- Allow you to select supported platforms.
- Register platform applications with the Firebase project.
- Generate the Firebase configuration file.
- Keep Firebase configuration synchronized with the selected platforms.
Firebase recommends rerunning flutterfire configure when you add a new platform or start using certain additional Firebase products so that the configuration remains current. :contentReference[oaicite:7]{index=7}
13. firebase_options.dart
The FlutterFire CLI generates a file named firebase_options.dart.
A typical project structure can look like:
firebase_flutter_app/
├── android/
├── ios/
├── lib/
│ ├── firebase_options.dart
│ └── main.dart
├── web/
├── test/
└── pubspec.yaml
The generated configuration contains platform-specific Firebase configuration values. Firebase describes the identifiers in this configuration as unique but non-secret identifiers. :contentReference[oaicite:8]{index=8}
14. Add Firebase Core
The firebase_core package is used to initialize Firebase in a Flutter application.
flutter pub add firebase_core
After adding the package, run the configuration command again if required:
flutterfire configure
The official setup process installs firebase_core, configures the project, initializes Firebase, and then rebuilds the application. :contentReference[oaicite:9]{index=9}
15. Initialize Firebase
Open lib/main.dart and import Firebase Core and the generated configuration file:
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
Initialize Firebase before starting the Flutter application:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
This is the initialization pattern documented by Firebase for Flutter applications. :contentReference[oaicite:10]{index=10}
16. Complete Firebase Initialization Example
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Firebase & Flutter'),
),
body: const Center(
child: Text(
'Firebase initialized successfully!',
),
),
),
);
}
}
17. Why WidgetsFlutterBinding.ensureInitialized() Is Used
Firebase initialization happens before runApp(). Because the application is performing asynchronous initialization before the Flutter application starts, WidgetsFlutterBinding.ensureInitialized() ensures that Flutter's binding is initialized first.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
18. Adding Firebase Products
Firebase functionality is added through individual Flutter plugins. For example, Authentication uses firebase_auth, while Cloud Firestore uses cloud_firestore.
flutter pub add firebase_auth
flutter pub add cloud_firestore
flutter pub add firebase_storage
After adding Firebase plugins, Firebase recommends running flutterfire configure and rebuilding the project as appropriate. :contentReference[oaicite:11]{index=11}
19. Firebase Authentication
Firebase Authentication provides services for managing user identity and authentication.
Common authentication methods include:
- Other supported identity providers
Add Firebase Authentication:
flutter pub add firebase_auth
20. Import Firebase Authentication
import 'package:firebase_auth/firebase_auth.dart';
Create an authentication instance:
final FirebaseAuth auth = FirebaseAuth.instance;
21. Create a User with Email and Password
Future registerUser(
String email,
String password,
) async {
try {
final credential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: email,
password: password,
);
print(credential.user?.uid);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
22. Sign In with Email and Password
Future loginUser(
String email,
String password,
) async {
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(
email: email,
password: password,
);
print('Login successful');
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
23. Sign Out
Future logoutUser() async {
await FirebaseAuth.instance.signOut();
}
24. Check Current User
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
print('Logged in user: ${user.email}');
} else {
print('No user is logged in');
}
25. Authentication State Changes
Firebase Authentication provides an authentication-state stream that can be used to react to login and logout changes.
StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasData) {
return const HomePage();
}
return const LoginPage();
},
)
26. Cloud Firestore
Cloud Firestore is a cloud-hosted NoSQL database. It stores data in collections and documents.
A simple structure can look like:
users
|
+-- userId1
| |
| +-- name
| +-- email
|
+-- userId2
|
+-- name
+-- email
Add Firestore:
flutter pub add cloud_firestore
27. Import Cloud Firestore
import 'package:cloud_firestore/cloud_firestore.dart';
28. Get Firestore Instance
final FirebaseFirestore firestore =
FirebaseFirestore.instance;
29. Add Data to Firestore
Future addUser() async {
await FirebaseFirestore.instance
.collection('users')
.add({
'name': 'Manish',
'email': '[email protected]',
'age': 25,
});
}
30. Add Data with a Specific Document ID
Future addUser() async {
await FirebaseFirestore.instance
.collection('users')
.doc('user001')
.set({
'name': 'Manish',
'email': '[email protected]',
});
}
31. Read a Firestore Document
Future getUser() async {
final document = await FirebaseFirestore.instance
.collection('users')
.doc('user001')
.get();
if (document.exists) {
print(document.data());
}
}
32. Read Multiple Firestore Documents
Future getUsers() async {
final snapshot = await FirebaseFirestore.instance
.collection('users')
.get();
for (final document in snapshot.docs) {
print(document.data());
}
}
33. Display Firestore Data with StreamBuilder
Firestore can provide a stream of changes, allowing the Flutter UI to react when the database changes.
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('users')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return const Text(
'Something went wrong.',
);
}
final documents = snapshot.data?.docs ?? [];
if (documents.isEmpty) {
return const Text(
'No users found.',
);
}
return ListView.builder(
itemCount: documents.length,
itemBuilder: (context, index) {
final data =
documents[index].data()
as Map;
return ListTile(
title: Text(data['name'] ?? ''),
subtitle: Text(data['email'] ?? ''),
);
},
);
},
)
34. Update Firestore Data
Future updateUser() async {
await FirebaseFirestore.instance
.collection('users')
.doc('user001')
.update({
'name': 'Updated Name',
});
}
35. Delete Firestore Data
Future deleteUser() async {
await FirebaseFirestore.instance
.collection('users')
.doc('user001')
.delete();
}
36. Firebase Storage
Firebase Cloud Storage can be used for storing files such as images, videos, documents, and other user-generated content.
Add the Storage plugin:
flutter pub add firebase_storage
Import it:
import 'package:firebase_storage/firebase_storage.dart';
37. Uploading a File to Firebase Storage
final storageRef = FirebaseStorage.instance
.ref()
.child('images/profile.jpg');
await storageRef.putFile(file);
After uploading, you can obtain a download URL:
final downloadUrl =
await storageRef.getDownloadURL();
print(downloadUrl);
38. Firebase Cloud Messaging
Firebase Cloud Messaging, commonly called FCM, provides push messaging capabilities.
Add the messaging plugin:
flutter pub add firebase_messaging
Import the plugin:
import 'package:firebase_messaging/firebase_messaging.dart';
39. Request Notification Permission
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
print(
'Permission: ${settings.authorizationStatus}',
);
Platform-specific setup is required for push notifications, especially on Apple platforms. Firebase's current Flutter setup documentation notes Apple-specific requirements for Cloud Messaging, including push-notification configuration in Xcode. :contentReference[oaicite:12]{index=12}
40. Firebase Analytics
Firebase Analytics can help developers understand how users interact with an application.
Add Analytics:
flutter pub add firebase_analytics
Import it:
import 'package:firebase_analytics/firebase_analytics.dart';
Create an Analytics instance:
final analytics = FirebaseAnalytics.instance;
Log an event:
await analytics.logEvent(
name: 'button_clicked',
parameters: {
'button_name': 'signup',
},
);
41. Firebase Crashlytics
Crashlytics can be used to monitor application crashes and help developers understand problems occurring in deployed applications.
Add the package:
flutter pub add firebase_crashlytics
Import it:
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
42. Recording an Error with Crashlytics
try {
// Some application code
} catch (error, stackTrace) {
await FirebaseCrashlytics.instance.recordError(
error,
stackTrace,
);
}
43. Firebase Remote Config
Remote Config allows applications to use remotely controlled configuration values. It can be useful when application behavior or configuration needs to be changed without publishing a new application version for every configuration change.
Add the plugin:
flutter pub add firebase_remote_config
44. Firebase and API-Based Applications
Firebase and REST APIs can both be used in a Flutter application. They solve different types of problems.
| Firebase |
REST API |
| Provides managed backend services |
Provides access to server-defined endpoints |
| Authentication can use Firebase Auth |
Authentication depends on the API |
| Firestore provides cloud database functionality |
Backend API provides data through HTTP |
| FlutterFire plugins provide Dart integration |
Packages such as http can call endpoints |
45. Firebase Security Rules
Firebase database and storage services use security rules to control access. Rules should be designed according to the application's authentication and authorization requirements.
A simplified Firestore rule example is:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write:
if request.auth != null;
}
}
}
This example requires the user to be authenticated before allowing access. Production applications should use rules appropriate to their actual data model and authorization requirements.
46. Authentication and Firestore Together
A common application architecture is to authenticate the user first and then use the authenticated user's ID when storing or retrieving Firestore data.
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
await FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.set({
'name': 'User Name',
'email': user.email,
});
}
47. Firebase Loading and Error Handling
Firebase operations are asynchronous and should be handled using appropriate loading and error states.
bool isLoading = false;
Future saveUser() async {
setState(() {
isLoading = true;
});
try {
await FirebaseFirestore.instance
.collection('users')
.add({
'name': 'Flutter User',
});
} catch (e) {
print('Error: $e');
} finally {
if (mounted) {
setState(() {
isLoading = false;
});
}
}
}
48. Firebase Exception Handling
Firebase plugins can expose product-specific exceptions. For example, Authentication operations commonly use FirebaseAuthException.
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'invalid-credential') {
print('Invalid credentials');
} else if (e.code == 'user-disabled') {
print('This user account is disabled');
} else {
print('Authentication error: ${e.message}');
}
}
49. Firebase Project Structure
Flutter App
│
├── lib/
│ ├── main.dart
│ ├── firebase_options.dart
│ ├── models/
│ ├── services/
│ ├── screens/
│ └── widgets/
│
├── android/
├── ios/
├── web/
└── pubspec.yaml
50. Recommended Service Layer
For larger applications, Firebase operations can be placed inside service classes rather than writing database or authentication code directly inside widgets.
class UserService {
final FirebaseFirestore firestore =
FirebaseFirestore.instance;
Future createUser(
String id,
String name,
String email,
) async {
await firestore
.collection('users')
.doc(id)
.set({
'name': name,
'email': email,
});
}
Future getUser(
String id,
) async {
return firestore
.collection('users')
.doc(id)
.get();
}
}
51. Flutter + Firebase Application Flow
User
|
v
Flutter UI
|
v
Service / ViewModel
|
v
FlutterFire Plugin
|
v
Firebase Service
|
v
Firebase Backend
|
v
Response
|
v
Flutter UI Update
52. Firebase Authentication Flow
Login Screen
|
v
Email + Password
|
v
FirebaseAuth
|
v
Firebase Authentication
|
+--------+
| |
Success Error
| |
v v
Home Page Error UI
53. Firestore Data Flow
Flutter Widget
|
v
UserService
|
v
Cloud Firestore Plugin
|
v
Firestore Database
|
v
Document / Collection
|
v
Flutter UI
54. Common Firebase Services Used in Flutter
| Service |
Typical Use |
| Firebase Authentication |
Login, registration, identity management |
| Cloud Firestore |
Cloud NoSQL application data |
| Realtime Database |
Realtime synchronized application data |
| Cloud Storage |
Images, videos, and files |
| Cloud Messaging |
Push notifications |
| Analytics |
Usage and event analytics |
| Crashlytics |
Crash monitoring |
| Remote Config |
Remote application configuration |
| Cloud Functions |
Backend/server-side functions |
| App Check |
Helps protect backend resources from abuse |
55. When Should You Use Firebase?
Firebase can be useful when an application requires managed backend services and you want to integrate those services into Flutter using FlutterFire plugins.
Examples include:
- Social media applications
- Task management applications
- Authentication-based applications
- Applications requiring cloud file storage
- Applications requiring push notifications
- Applications requiring realtime database updates
56. Firebase Emulator
Firebase provides local emulation capabilities for supported services. This can be useful for development and testing without relying entirely on production Firebase resources.
Firebase's Flutter setup documentation also shows that a demo project ID can be used when initializing Firebase with the Firebase Emulator. :contentReference[oaicite:13]{index=13}
await Firebase.initializeApp(
demoProjectId: 'demo-project-id',
);
57. Important Firebase Setup Commands
| Command |
Purpose |
firebase login |
Sign in to Firebase CLI |
dart pub global activate flutterfire_cli |
Install FlutterFire CLI |
flutterfire configure |
Configure Firebase for the Flutter project |
flutter pub add firebase_core |
Add Firebase Core |
flutter pub add firebase_auth |
Add Firebase Authentication |
flutter pub add cloud_firestore |
Add Cloud Firestore |
flutter pub add firebase_storage |
Add Firebase Storage |
flutter pub add firebase_messaging |
Add Firebase Cloud Messaging |
58. Common Firebase and Flutter Mistakes
- Forgetting to initialize Firebase before using Firebase services.
- Forgetting to run
flutterfire configure.
- Adding a Firebase plugin without configuring the application correctly.
- Using incorrect Firebase project configuration.
- Forgetting to register the required platform.
- Not handling authentication exceptions.
- Not handling Firestore or Storage errors.
- Writing insecure database or storage rules.
- Putting all Firebase logic directly inside UI widgets.
- Ignoring loading and empty states.
- Not testing Firebase functionality on the target platforms.
59. Best Practices
- Keep Firebase initialization in a central application entry point.
- Use the official FlutterFire plugins.
- Keep Firebase service operations separated from presentation code.
- Use models for structured application data.
- Handle Firebase exceptions appropriately.
- Provide loading, success, empty, and error states.
- Design Firestore and Storage security rules carefully.
- Do not expose passwords or sensitive credentials in source code.
- Use authentication and authorization rules appropriate to the application.
- Test Firebase integrations before releasing the application.
- Keep Firebase configuration synchronized when adding platforms or Firebase products.
60. Complete Beginner Workflow
- Install Flutter.
- Create a Flutter application.
- Create or select a Firebase project.
- Install Firebase CLI.
- Log in using
firebase login.
- Install FlutterFire CLI.
- Run
flutterfire configure.
- Add
firebase_core.
- Initialize Firebase in
main.dart.
- Add the Firebase plugin required by your application.
- Implement the required Firebase functionality.
- Handle loading and error states.
- Configure security rules.
- Test the application.
- Build and deploy the application.
61. Practical Mini Project: Firebase User App
A beginner-friendly Firebase project can contain the following features:
- Authentication state handling
- User profile stored in Firestore
- Profile image stored in Firebase Storage
62. Mini Project Architecture
lib/
├── main.dart
├── firebase_options.dart
├── models/
│ └── user_model.dart
├── services/
│ ├── auth_service.dart
│ ├── user_service.dart
│ └── storage_service.dart
├── screens/
│ ├── login_page.dart
│ ├── register_page.dart
│ ├── home_page.dart
│ └── profile_page.dart
└── widgets/
├── loading_widget.dart
└── error_widget.dart
63. Interview Questions
- What is Firebase?
- What is FlutterFire?
- Why is Firebase commonly used with Flutter?
- What is
firebase_core?
- Why is
Firebase.initializeApp() required?
- What is
firebase_options.dart?
- What does
flutterfire configure do?
- What is Firebase Authentication?
- What is Cloud Firestore?
- What is the difference between Firestore and Realtime Database?
- What is Firebase Storage?
- What is Firebase Cloud Messaging?
- What is Firebase Analytics?
- What is Firebase Crashlytics?
- How do you create a Firebase user using email and password?
- How do you sign out a Firebase user?
- How do you read a Firestore document?
- How do you add data to Firestore?
- How do you update a Firestore document?
- How do you delete a Firestore document?
- How do you handle Firebase exceptions?
- Why are Firebase security rules important?
- What is the purpose of FlutterFire CLI?
64. Practice Exercise
Create a Flutter application using Firebase with the following features:
- Create a Firebase project.
- Connect the Flutter project using FlutterFire CLI.
- Initialize Firebase.
- Add Firebase Authentication.
- Create a registration screen.
- Create a login screen.
- Implement email/password authentication.
- Create a logout button.
- Add Cloud Firestore.
- Store user profile information.
- Display user information in the Flutter UI.
- Add update and delete functionality.
- Add loading indicators.
- Add error handling.
- Implement an empty state when no records exist.
- Test the application on your target platform.
65. Quick Revision
| Concept |
Key Point |
| Firebase |
Platform providing backend and application services |
| FlutterFire |
Official Flutter plugins for Firebase services |
| Firebase Core |
Used to initialize Firebase |
| FlutterFire CLI |
Configures Firebase for Flutter projects |
| firebase_options.dart |
Generated Firebase configuration for supported platforms |
| Firebase Auth |
User authentication |
| Cloud Firestore |
Cloud-hosted NoSQL database |
| Realtime Database |
Realtime synchronized database |
| Cloud Storage |
File and media storage |
| Cloud Messaging |
Push messaging |
| Analytics |
Application usage analytics |
| Crashlytics |
Crash monitoring |
| Remote Config |
Remote configuration |
| Security Rules |
Control access to Firebase resources |
66. Summary
Firebase and Flutter can be combined to build applications that require backend functionality such as authentication, cloud databases, file storage, push notifications, analytics, and crash reporting. FlutterFire provides Flutter plugins that allow developers to access these Firebase services from Dart.
The basic integration process is to create or select a Firebase project, install the Firebase and FlutterFire command-line tools, run flutterfire configure, add firebase_core, initialize Firebase, and then add the plugins required by the application. :contentReference[oaicite:14]{index=14}
Once Firebase is initialized, individual services such as Authentication, Cloud Firestore, Storage, Messaging, Analytics, and Crashlytics can be integrated as needed. A well-structured Flutter application should keep Firebase operations organized, handle loading and errors, and apply appropriate security rules.
67. Useful Resources
68. JustAcademy Flutter Training
Learn Flutter development through structured practical training covering Dart programming, Flutter UI development, Firebase integration, API integration, state management, and application development.
Explore JustAcademy Flutter Training Course
Register for Flutter Course Demo